﻿#include "ui/listview.h"
#include "ui/canvas.h"
#include "draw.h"

using namespace anip;

ui::ListView::Item::Item(ListView& list, const wstring& text) :
	ButtonBase(list._panel, { 0, 0 }, { 50, 50 }, text),
	_cv(new Canvas()), _list(list)
{
	layoutOptions.type = Control::LayoutOptions::Flow;
	//setMargins({ 5, 5 }, { 5, 5 }); // use settings?
	addChild(*_cv);
	_cv->fitType = Canvas::FitType::Rescale;
	_update();
}

void ui::ListView::Item::processMouseButton(MouseButton btn, ButtonAction action)
{
	if (enabled && _list.allowSelect && action == ButtonAction::Down)
		select();
	ButtonBase::processMouseButton(btn, action);
}

bool ui::ListView::Item::canBeginDrag(MouseButton btn, invec2 pos)
{
	return _list.allowDrag;
}

void ui::ListView::Item::processDrag(invec2 start, invec2 pos)
{
	postSignal({ ui::Signal::Type::NeedsRedraw });
	_dragPos = _pos + pos - start;
	_dragMouse = _pos + pos;
}

void ui::ListView::Item::processEndDrag()
{
	if (!_list.onItemDrag) return;

	ANIP_ui_LoopOverChildrenFrom(_list.firstItem(), ctrl)
	{
		if (math::inRectangle(_dragMouse - ctrl->position(), { 0, 0 }, ctrl->size()))
		{
			_list.onItemDrag(_list, *this, (Item&)*ctrl);
			return;
		}
	}
}

void ui::ListView::Item::select(bool s)
{
	if (s == _select) return;
	if (s)
	{
		if (!_list.allowMultipleSelect)
		{
			for (auto i : _list._selection)
				i->_select = false;
			_list._selection.clear();
		}
		_list._selection.insert(this);
		_select = true;
	}
	else
	{
		_list._selection.erase(this);
		_select = false;
	}
	postSignal({ ui::Signal::Type::NeedsRedraw });
}

void ui::ListView::Item::_update()
{
	_size = _list._itemSize;
	_cv->setSize(_size - vec2{ 10.0f, r::ListViewItem_TextHeight + 5.0f });
	_cv->setPosition({ 5.0f, 5.0f });
}

//void ui::ListView::Item::applyTheme(Theme& t)
//{
//	//normalColor = { 0.0f, 0.0f, 0.0f, 0.0f };
//}

int ui::ListView::Item::getTextWidth()
{
	return (int)(_size.x - 10 - 0.6f * r::RoundRadius);
}

void ui::ListView::Item::setImage(const Texture2D* tex)
{
	if (tex == _cv->texture) return;
	postSignal({ ui::Signal::Type::NeedsRedraw });
	_cv->texture = tex;
}

const Texture2D* ui::ListView::Item::getImage() const
{
	return _cv->texture;
}

void ui::ListView::Item::paint()
{
	color col = _select ? selectedColor : normalColor;
	if (_press) col = col.mulWithoutAlpha(pressFactor);
	else if (_hover) col = col.mulWithoutAlpha(hoverFactor);

	if (_hover || _select)
		Draw::roundedRect(_absPos, _size, r::RoundRadius, col);

	_cv->paint();

	auto textTex = getTextTexture();
	if (textTex != nullptr)
	{
		float height = r::ListViewItem_TextHeight;
		vec2 tsize = textTex->size();
		vec2 tpos = _absPos + vec2{ (_size.x - tsize.x) * 0.5f, _size.y - height };
		if (_select)
		{
			Context::noScissor();
			//Context::setScissor(_list._absPos, _list._size);
			Draw::roundedRect({ _absPos.x, tpos.y }, { _size.x, tsize.y },
				r::RoundRadius, col);
		} else
			Context::setScissor(_absPos, _size - vec2{ 0, 5 });
		Draw::text(tpos, tsize, *textTex, textColor);
	}

	if (isDragging())
	{
		Context::noScissor();
		Draw::rect(_parent->toAbsolutePos(_dragPos), _size, { 0.5f, 0.5f, 0.8f, 0.5f });
	}
}

void ui::ListView::Item::flow(Flow& f)
{
	_update();
	flowChildrenDefault();
	defaultFlowLayout(f);
}

ui::ListView::ListView(Container* parent, invec2 pos, invec2 size):
	Control(parent, pos, size),
	_panel(new Scrollable<Panel>((Container*)this)),
	_header(new Header(/*(Container*)this)*/)), header(*_header)
{
	_panel->layoutOptions.dock = Control::LayoutOptions::DockType::Fill;
	_panel->onMouseButton = [&](Control& self, MouseButton btn, ButtonAction action)
	{
		if (action == ButtonAction::Down && ((Container&)self).hoveredChild() == nullptr)
			clearSelection();
	};
}

ui::ListView::Item& ui::ListView::addItem(const wstring& text)
{
	auto i = new Item(*this, text);
	//postSignal({ ui::Signal::Type::NeedsRedraw });
	postSignal({ ui::Signal::Type::NeedsReflow });
	return *i;
}

void ui::ListView::clearAllItems()
{
	ANIP_ui_LoopOverChildrenFrom(_panel->firstChild(), i)
	{
		i->markDelete();
	}
	//postSignal({ ui::Signal::Type::NeedsRedraw });
	postSignal({ ui::Signal::Type::NeedsReflow });
}

void ui::ListView::clearSelection()
{
	while (!_selection.empty())
	{
		(*_selection.begin())->select(false);
	}
}

void ui::ListView::paint()
{
	//_header->paint()
	_panel->paint();
}